package com.lld.im.tcp.server;


import com.lld.im.codec.MessageDecoder;
import com.lld.im.codec.MessageEncoder;
import com.lld.im.codec.config.BootstrapConfig;
import com.lld.im.tcp.handler.HeartBeatHandler;
import com.lld.im.tcp.handler.NettyServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @author: LunBoWang
 * @description: 创建并启动一个基于 Netty 的 TCP 服务器。
 * 该类使用 Netty 框架来处理网络事件，包括客户端连接、数据读写和心跳检测。
 * 它通过配置和初始化 ServerBootstrap 来创建服务器实例，并为每个新连接的通道添加自定义的 ChannelHandler 来处理网络事件。
 * 该类还提供了启动服务器的方法 start()，用于绑定指定的端口并启动服务器。
 * @className: LimServer
 * @packageName: com.lld.im.tcp.server
 * @date: 2025/3/26 下午6:26
 * @version: 1.0
 */

/**
 * LimServer 类用于创建并启动一个基于 Netty 的 TCP 服务器。
 */
public class LimServer {
    BootstrapConfig.TcpConfig config;
    NioEventLoopGroup mainGroup;
    NioEventLoopGroup subGroup;
    ServerBootstrap server;

    public LimServer(BootstrapConfig.TcpConfig config) {
        this.config = config;
        // 初始化主事件循环组，用于处理客户端连接
        mainGroup = new NioEventLoopGroup(config.getBossThreadSize());
        // 初始化子事件循环组，用于处理网络读写
        subGroup = new NioEventLoopGroup(config.getWorkThreadSize());
        // 创建一个 ServerBootstrap 实例，用于启动服务器
        server = new ServerBootstrap();
        // 配置主事件循环组和子事件循环组
        server.group(mainGroup, subGroup)
                // 指定使用 NioServerSocketChannel 作为服务器通道
                .channel(NioServerSocketChannel.class)
                // 设置服务器端的 backlog 队列大小,它决定了服务器在无法立即处理新连接时，可以暂存多少等待处理的连接请求。
                .option(ChannelOption.SO_BACKLOG, 10240)
                // 允许地址重用
                .option(ChannelOption.SO_REUSEADDR, true)
                // 禁用 Nagle 算法，减少延迟
                .childOption(ChannelOption.TCP_NODELAY, true)
                // 启用 TCP 保持活动状态
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                // 为每个新连接的通道添加一个 ChannelInitializer
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        // 这里可以添加自定义的 ChannelHandler 来处理网络事件
                        ch.pipeline().addLast(new MessageDecoder());
                        ch.pipeline().addLast(new MessageEncoder());
//                        ch.pipeline().addLast(new IdleStateHandler(
//                                0,0,1
//                        ));
                        ch.pipeline().addLast(new HeartBeatHandler(config.getHeartBeatTime()));
                        ch.pipeline().addLast(new NettyServerHandler(config.getBrokerId(),config.getLogicUrl()));
                    }
                });
    }
    public void start(){
        server.bind(this.config.getTcpPort());
    }
}